package com.ybkj.daijia.api.driver.v3;

import com.ybkj.daijia.Setting;
import com.ybkj.daijia.serverUtils.SettingUtils;
import com.ybkj.daijia.api.driver.Error;
import com.ybkj.daijia.api.driver.ErrorConstant;
import com.ybkj.daijia.api.driver.SecurityUtils;
import com.ybkj.daijia.api.driver.transport.ResultTransport;
import com.ybkj.daijia.common.Result;
import com.ybkj.daijia.server.errand.Order;
import com.ybkj.daijia.server.errand.Order.PayTypeDetails;
import com.ybkj.daijia.server.event.model.errand.PaotuiOrderFinishEvent;
import com.ybkj.daijia.server.mc.Enterprise;
import com.ybkj.daijia.server.mc.Passenger;
import com.ybkj.daijia.server.mc.PassengerConcats;
import com.ybkj.daijia.server.model.Area;
import com.ybkj.daijia.server.model.Company;
import com.ybkj.daijia.server.model.Driver;
import com.ybkj.daijia.server.service.AreaService;
import com.ybkj.daijia.server.service.CompanyService;
import com.ybkj.daijia.server.service.DriverService;
import com.ybkj.daijia.server.service.ErrandService;
import com.ybkj.daijia.server.service.MemberService;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.ApplicationEventMulticaster;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @author bo
 */
@Controller("driverErrandV3Controller")
@RequestMapping(value = "driver/api/rest/v3")
public class ErrandController {

    private static final Logger logger = LoggerFactory.getLogger(ErrandController.class);

    @Autowired
    private DriverService driverService;

    @Autowired
    private ErrandService errandService;

    @Autowired
    private MemberService memberService;

    @Autowired
    private AreaService areaService;

    @Autowired
    private SettingUtils settingUtils;

    @Autowired
    private ApplicationEventMulticaster applicationEventMulticaster;

    @Autowired
    private CompanyService companyService;

    @RequestMapping(value = "completePaotuiTask", method = RequestMethod.POST)
    public @ResponseBody
    ResultTransport completeTask(
        HttpServletResponse response,
        Long driverId, Long orderId,
        Double shouldPay, Double mileage, Double mileageMoney,
        Integer waitedTime, Double waitedMoney, Double qibuMoney,
        Long travelBeginTime,
        String appKey, String token, String timestamp) {

        response.setHeader("Access-Control-Allow-Origin", "*");

        logger.debug(
            "recv driverId:{},orderId:{},shouldPay:{},mileage:{},mileageMoney:{},waitedTime:{},waitedMoney:{},qibuMoney:{},travelBeginTime:{},appKey:{},token:{},timestamp:{}",
            driverId, orderId, shouldPay, mileage, mileageMoney, waitedTime, waitedMoney, qibuMoney,
            travelBeginTime, appKey, token, timestamp);

        if (null == driverId || null == orderId || null == shouldPay || null == mileage
            || null == mileageMoney || null == waitedTime || null == waitedMoney
            || null == qibuMoney || null == travelBeginTime ||
            SecurityUtils.isBlank(appKey, token, timestamp)) {

            return ResultTransport.getErrorBy(ErrorConstant.PARAM_ERROR);

        }

        if (!StringUtils.isNumeric(timestamp) || !SecurityUtils
            .checkTimestamp(Long.parseLong(timestamp))) {
            return ResultTransport.getErrorBy(ErrorConstant.TIMESTAMP_ERROR);
        }

        List<String> params = new LinkedList<String>();
        params.add(String.valueOf(driverId));
        params.add(String.valueOf(orderId));
        params.add(String.valueOf(shouldPay));
        params.add(String.valueOf(mileage));
        params.add(String.valueOf(mileageMoney));
        params.add(String.valueOf(waitedTime));
        params.add(String.valueOf(waitedMoney));
        params.add(String.valueOf(qibuMoney));
        params.add(String.valueOf(travelBeginTime));
        params.add(timestamp);
        params.add(appKey);

        if (!SecurityUtils.checkToken(params, token)) {
            return ResultTransport.getErrorBy(ErrorConstant.TOKEN_ERROR);
        }

        try {

            Driver driver = driverService.findOne(driverId);

            if (null == driver) {
                return ResultTransport.getErrorBy(ErrorConstant.DRIVER_NOT_EXISTS);
            }

            Order order = errandService.findOne(orderId);
            if (null == order) {
                return ResultTransport.getErrorBy(ErrorConstant.ORDER_NOT_EXISTS_ERROR);
            }

            if (!order.getStatus().equals(Order.ORDER_STATUS_ZHIXING)) {
                return ResultTransport.getErrorBy(ErrorConstant.ORDER_STATUS_ERROR);
            }

            if (!order.getEmployId().equals(driverId)) {
                return ResultTransport.getErrorBy(ErrorConstant.ORDER_DRIVER_OWNER_ERROR);
            }

            Passenger passenger = memberService.findOnePassengerByPhone(order.getPassengerPhone());

            Map<String, Object> map = new HashMap<String, Object>();

            order.setShouldPay(shouldPay);

            double m = new BigDecimal(mileage).setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue();

            Company company = companyService.findOne(order.getCompanyId());

            map.put("orderId", order.getId());
            map.put("orderNumber", order.getOrderNo());
            map.put("orderCompanyName", company.getAbbreviation());

            map.put("memberPhone", order.getPassengerPhone());
            map.put("memberName", order.getPassengerName());

            if (null != passenger) {
                map.put("memberType", passenger.getTypeStr());

                if (passenger.getType() == Passenger.TYPE_PASSENGER) {
                    map.put("memberCompanyName", "");
                    map.put("isOverdraw", passenger.isAllowOverdraw());
                    map.put("virtual", passenger.getDrawMoney());
                } else if (passenger.getType() == Passenger.TYPE_ENTERPRISE) {
                    Enterprise enterprise = memberService
                        .findOneEnterprise(passenger.getEnterprise_id());
                    map.put("memberCompanyName", enterprise.getName());
                    map.put("isOverdraw", enterprise.isAllowOverdraw());
                    map.put("virtual", enterprise.getDrawMoney());
                }

                List<PassengerConcats> concatslist = errandService
                    .findPassengerConcats(passenger.getId());
                PassengerConcats passengerConcats = null;
                if (!CollectionUtils.isEmpty(concatslist)) {
                    passengerConcats = concatslist.get(0);
                }
                if (null != passengerConcats) {
                    map.put("memberEcp", passengerConcats.getPhone());
                    map.put("memberEcn", passengerConcats.getName());
                }

            } else {
                map.put("memberCompanyName", "");
                map.put("isOverdraw", false);
                map.put("virtual", 0);

                map.put("memberEcp", "");
                map.put("memberEcn", "");
            }

            if (order.getErrandFixPrice()) {//定价
                map.put("qibuMoney", BigDecimal.ZERO);
                map.put("mileageMoney", BigDecimal.ZERO);
                map.put("waitedMoney", BigDecimal.ZERO);
            } else {
                map.put("qibuMoney", qibuMoney);
                map.put("mileageMoney", mileageMoney);
                map.put("waitedMoney", waitedMoney);
            }

            //form data
            map.put("driverId", driverId);
            map.put("shouldCash", shouldPay);
            map.put("mileage", m);
            map.put("waitedTime", waitedTime);
            map.put("travelBeginTime", travelBeginTime);

            //setting
            Setting setting = settingUtils.get();
            map.put("allowModifyCash", setting.isAllowModifyCash());
            map.put("ctx", setting.getWebUrl());

            ResultTransport instance = ResultTransport.getErrorBy(ErrorConstant.SUCCESS);
            instance.setData(map);

            return instance;

        } catch (Exception e) {
            logger.error("api v3 driver completePaotuiTask error: {}", e);
            return ResultTransport.getErrorBy(ErrorConstant.SERVER_ERROR);
        }

    }

    @RequestMapping(value = "completePaotuiTask2")
    public @ResponseBody
    String completePaotuiTask2(
        HttpServletResponse response,
        Long driverId, Long orderId,
        Double cashMoney, Double signMoney, Double balanceMoney,
        PayTypeDetails payTypeDetails,
        Double shouldCash, Double realCash, Double mileage, Integer waitedTime,
        Long travelBeginTime) {

        response.setCharacterEncoding("utf-8");

        logger.debug("recv driverId:{},orderId:{},"
                + "cashMoney:{},signMoney:{},balanceMoney:{},"
                + "payTypeDetails:{},"
                + "shouldCash:{},realCash:{},mileage:{},waitedTime:{},travelBeginTime:{}",
            driverId, orderId, cashMoney, signMoney, balanceMoney, payTypeDetails, shouldCash,
            realCash, mileage, waitedTime, travelBeginTime);

        if (null == driverId || null == orderId || null == payTypeDetails ||
            null == shouldCash || null == realCash || null == mileage || null == waitedTime
            || null == travelBeginTime) {
            return "callback({code:" + ErrorConstant.PARAM_ERROR.getMessage() + "})";
        }

        try {

            Driver driver = driverService.findOne(driverId);

            if (null == driver) {
                return "callback({code:" + ErrorConstant.DRIVER_NOT_EXISTS.getMessage() + "})";
            }

            Order order = errandService.findOne(orderId);
            if (null == order) {
                return "callback({code:" + ErrorConstant.ORDER_NOT_EXISTS_ERROR.getMessage() + "})";
            }

            if (!order.getStatus().equals(Order.ORDER_STATUS_ZHIXING)) {
                return "callback({code:" + ErrorConstant.ORDER_STATUS_ERROR.getMessage() + "})";
            }

            if (!order.getEmployId().equals(driverId)) {
                return "callback({code:" + ErrorConstant.ORDER_DRIVER_OWNER_ERROR.getMessage()
                    + "})";
            }

            order.setCashMoney(cashMoney);
            order.setSignMoney(signMoney);
            order.setBalanceMoney(balanceMoney);

            order.setShouldPay(shouldCash);
            order.setRealPay(realCash);
            order.setStatus(Order.ORDER_STATUS_OK);

            BigDecimal m = new BigDecimal(mileage);
            double df = m.setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue();
            order.setMileage(df);

            order.setWaitedTime(waitedTime);
            order.setPayTypeDetails(payTypeDetails);
            order.setTravelTime((int) ((System.currentTimeMillis() - travelBeginTime) / (1000 * 60)));

            Result<Order> result = errandService.completeTask(order);

            if (result.isSuccess()) {
                PaotuiOrderFinishEvent finishEvent = new PaotuiOrderFinishEvent(result.getResult());
                applicationEventMulticaster.multicastEvent(finishEvent);

                return "callback({code:" + ErrorConstant.SUCCESS.getCode() + "})";
            } else {
                return "callback({code:" + result.getMessage() + "})";
            }

        } catch (Exception e) {
            logger.error("api v3 driver completeTask2 error: {}", e);
            return "callback({code:" + ErrorConstant.SERVER_ERROR.getMessage() + "})";
        }

    }

    @RequestMapping(value = "completePaotuiTask3", method = RequestMethod.POST)
    public @ResponseBody
    ResultTransport completePaotuiTask3(
        Long driverId, Long orderId,
        Double cashMoney, Double signMoney, Double balanceMoney,
        PayTypeDetails payTypeDetails,
        Double shouldCash, Double realCash, Double mileage, Integer waitedTime, Integer travelTime,
        String appKey, String token, String timestamp) {

        logger.debug("recv driverId:{},orderId:{},"
                + "cashMoney:{},signMoney:{},balanceMoney:{},"
                + "payTypeDetails:{},"
                + "shouldCash:{},realCash:{},mileage:{},waitedTime:{},travelTime:{},appKey:{},token:{},timestamp:{}",
            driverId, orderId, cashMoney, signMoney, balanceMoney, payTypeDetails, shouldCash,
            realCash, mileage, waitedTime, travelTime, appKey, token, timestamp);

        if (null == driverId || null == orderId || null == payTypeDetails ||
            null == shouldCash || null == realCash || null == mileage || null == waitedTime
            || null == travelTime ||
            SecurityUtils.isBlank(appKey, token, timestamp)) {
            return ResultTransport.getErrorBy(ErrorConstant.PARAM_ERROR);
        }

        if (!StringUtils.isNumeric(timestamp) || !SecurityUtils
            .checkTimestamp(Long.parseLong(timestamp))) {
            return ResultTransport.getErrorBy(ErrorConstant.TIMESTAMP_ERROR);
        }

        List<String> params = new LinkedList<String>();
        params.add(String.valueOf(driverId));
        params.add(String.valueOf(orderId));
        params.add(String.valueOf(cashMoney));
        params.add(String.valueOf(signMoney));
        params.add(String.valueOf(balanceMoney));
        params.add(payTypeDetails.toString());
        params.add(String.valueOf(shouldCash));
        params.add(String.valueOf(realCash));
        params.add(String.valueOf(mileage));
        params.add(String.valueOf(waitedTime));
        params.add(String.valueOf(travelTime));
        params.add(timestamp);
        params.add(appKey);

        if (!SecurityUtils.checkToken(params, token)) {
            return ResultTransport.getErrorBy(ErrorConstant.TOKEN_ERROR);
        }

        try {

            Driver driver = driverService.findOne(driverId);

            if (null == driver) {
                return ResultTransport.getErrorBy(ErrorConstant.DRIVER_NOT_EXISTS);
            }

            Order order = errandService.findOne(orderId);
            if (null == order) {
                return ResultTransport.getErrorBy(ErrorConstant.ORDER_NOT_EXISTS_ERROR);
            }

            if (!order.getStatus().equals(Order.ORDER_STATUS_ZHIXING)) {
                return ResultTransport.getErrorBy(ErrorConstant.ORDER_STATUS_ERROR);
            }

            if (!order.getEmployId().equals(driverId)) {
                return ResultTransport.getErrorBy(ErrorConstant.ORDER_DRIVER_OWNER_ERROR);
            }

            order.setCashMoney(cashMoney);
            order.setSignMoney(signMoney);
            order.setBalanceMoney(balanceMoney);

            order.setShouldPay(shouldCash);
            order.setRealPay(realCash);
            order.setStatus(Order.ORDER_STATUS_OK);

            BigDecimal m = new BigDecimal(mileage);
            double df = m.setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue();
            order.setMileage(df);

            order.setWaitedTime(waitedTime);
            order.setPayTypeDetails(payTypeDetails);
            order.setTravelTime(travelTime);

            Result<Order> result = errandService.completeTask(order);

            if (result.isSuccess()) {
                PaotuiOrderFinishEvent finishEvent = new PaotuiOrderFinishEvent(result.getResult());
                applicationEventMulticaster.multicastEvent(finishEvent);

                return ResultTransport.getErrorBy(ErrorConstant.SUCCESS);
            } else {
                return ResultTransport.getErrorBy(new Error(-4, result.getMessage()));
            }

        } catch (Exception e) {
            logger.error("api v3 driver completeTask2 error: {}", e);
            return ResultTransport.getErrorBy(ErrorConstant.SERVER_ERROR);
        }

    }


    @RequestMapping(value = "getPaotuiOrderInfo")
    public @ResponseBody
    ResultTransport getPaotuiOrderInfo(Long orderId, String appKey, String token,
        String timestamp) {

        logger.debug("recv orderId:{},appKey:{},token:{},timestamp:{}", orderId, appKey, token,
            timestamp);

        if (null == orderId || SecurityUtils.isBlank(appKey, token, timestamp)) {
            return ResultTransport.getErrorBy(ErrorConstant.PARAM_ERROR);
        }

        if (!StringUtils.isNumeric(timestamp) || !SecurityUtils
            .checkTimestamp(Long.parseLong(timestamp))) {
            return ResultTransport.getErrorBy(ErrorConstant.TIMESTAMP_ERROR);
        }

        List<String> params = new LinkedList<String>();
        params.add(String.valueOf(orderId));
        params.add(timestamp);
        params.add(appKey);

        if (!SecurityUtils.checkToken(params, token)) {
            return ResultTransport.getErrorBy(ErrorConstant.TOKEN_ERROR);
        }

        Order order = errandService.findOne(orderId);

        if (null == order) {
            return ResultTransport.getErrorBy(ErrorConstant.ORDER_NOT_EXISTS_ERROR);
        }

        try {

            ResultTransport instance = ResultTransport.getErrorBy(ErrorConstant.SUCCESS);

            Company thisCompany = companyService.findOne(order.getCompanyId());
            if (null != thisCompany) {
                Passenger passenger = memberService.findOnePassenger(order.getPassengerId());
                if (null != passenger) {
                    Area paotuiArea = null;
                    if (passenger.getType().equals(Passenger.TYPE_PASSENGER)) {
                        paotuiArea = areaService.findPaotuiByPassenger(passenger.getId());
                    } else if (passenger.getType().equals(Passenger.TYPE_ENTERPRISE)) {
                        paotuiArea = areaService
                            .findPaotuiByEnterprise(passenger.getEnterprise_id());
                    }

                    if (null != paotuiArea) {
                        thisCompany.setArea(areaService.findOneWithCharge(paotuiArea.getId()));
                    } else {
                        thisCompany
                            .setArea(areaService.findOneWithCharge(thisCompany.getAreaPaotuiId()));
                    }
                } else {
                    thisCompany
                        .setArea(areaService.findOneWithCharge(thisCompany.getAreaPaotuiId()));
                }
            }

            order.setCompany(thisCompany);

            Map<String, Object> map = new HashMap<String, Object>();
            map.put("orderId", order.getId());
            map.put("orderNo", order.getOrderNo());
            map.put("title", order.getTitle());
            map.put("content", order.getContent());
            map.put("deliverTime", order.getDeliverTime());
            map.put("deliverAddress", order.getDeliverAddress());
            map.put("deliverLat", order.getDeliverLat());
            map.put("deliverLng", order.getDeliverLng());
            map.put("status", order.getStatus());
            map.put("shouldPay", order.getShouldPay());
            map.put("errandFixPrice", order.getErrandFixPrice());
            map.put("passengerId", order.getPassengerId());
            map.put("passengerName", order.getPassengerName());
            map.put("passengerPhone", order.getPassengerPhone());
            map.put("review", order.getReview());
            map.put("employName", order.getEmployName());
            map.put("employId", order.getEmployId());
            map.put("employPhone", order.getEmployPhone());
            if (null != thisCompany) {
                map.put("areaId", thisCompany.getArea().getId());
                map.put("chargeStartTimes", thisCompany.getArea().getChargeStartTimes());
            }

            instance.setData(map);

            return instance;

        } catch (Exception e) {
            logger.error("api v3 errand getPaotuiOrderInfo error: {}", e);
            return ResultTransport.getErrorBy(ErrorConstant.SERVER_ERROR);
        }
    }


}
